from socket import AF_INET, SOCK_DGRAM, socket
from json import dumps, loads
from random import randint, random
from time import sleep
def printf(type: str, *args):
	print(type, *args)
port1 = 10000
port2 = 10001
timeout = 3
# 创建一个TCP/IP套接字
bits = 1  # 1个bit，即2种状态
serial_numbers = 2 ** bits
window_size = 2 ** bits - 1  # 窗口大小
def delay():
	return random() * 0.1
def receive(type: str, port: int, file_name: str):
	global ACK
	ACK = -1
	sock = socket(AF_INET, SOCK_DGRAM)
	window_base = 0
	receive_datas = []
	# 绑定套接字到一个地址和端口号
	server_address = ('localhost', port)
	printf(type, 'starting up on %s port %s' % server_address)
	sock.bind(server_address)  # 监听传入的连接
	while True:
		sleep(random())
		if not randint(0, 3):  # 模拟迟到的数据包
			continue
		data, address = sock.recvfrom(4096)
		if not data:
			break
		data_json = loads(data.decode())
		temp_ACK = data_json["ACK"]
		if temp_ACK == window_base:
			receive_data = data_json["data"]
			if receive_data == "\0":
				break
			receive_datas.append(receive_data)
			printf(type, 'received %s bytes from %s: %s, ACK is %d' % (len(receive_data), address, receive_data, temp_ACK))  # 打印接收到的消息
			window_base = (window_base + 1) % serial_numbers
			ACK = temp_ACK
		else:
			printf(type, 'ACK is wrong', data_json)
		# 发送确认消息给客户端
		if randint(0, 3):
			confirm = dumps({"ACK": ACK})
			sock.sendto(confirm.encode(), address)  # 发送确认消息给客户端
			printf(type, f'sent: {confirm}')
		else:
			printf(type, 'confirmation not sent')
	with open(file_name, 'w') as f:
		f.write(''.join(receive_datas))
# 等待下一个数据包的到来
def send(type: str, port: int, send_data: list[str]):
	window_base = 0
	sock = socket(AF_INET, SOCK_DGRAM)
	# 连接到服务器地址和端口号
	server_address = ('localhost', port)
	try:
		current = 0
		while True:
			sleep(random())  # 模拟网络延迟
			# 发送数据给服务器
			if not send_data[current]:
				break
			data_to_send = send_data[current]
			message = dumps({"data": data_to_send, "ACK": window_base})
			if randint(0, 3):
				sock.sendto(message.encode(), server_address)
				printf(type, 'message sent:', message)
			else:
				printf(type, 'message not sent:', message)
			if data_to_send == "\0":
				break
			sock.settimeout(timeout)
			while True:
				sleep(random())
				if not randint(0, 3):  # 模拟迟到的数据包
					continue
				try:
					data, server = sock.recvfrom(16)
				except socket.timeout:
					printf(type, 'timeout occurred')
					break
				except Exception:
					continue
				if not randint(0, 3):  # 模拟丢包
					break
				if data:
					data_decode = loads(data.decode())
					ACK = data_decode["ACK"]
					if ACK == window_base:
						printf(type, 'received confirmation:', data_decode)
						window_base = (ACK + 1) % serial_numbers
						current += 1
					else:
						printf(type, 'ACK is wrong', data_decode)
				break
	# 等待下一个数据包的到来
	finally:
		# 关闭连接
		sock.close()
